#!/usr/bin/env perl
#
# Copyright (c) 2012-2013 Jeffrey M. Squyres.  All rights reserved.
#
# $COPYRIGHT$
# 
# Additional copyrights may follow
# 
# $HEADER$
#

package RubySlippers::Config;

use strict;
use RubySlippers::Messages;
use POSIX qw/floor/;

# Various configuration values

#-----------------------------------------------------------------------

# Private variables
my $config;

#-----------------------------------------------------------------------

#
# Function to strip leading and trailing whitespace, and remove
# comments
#
sub _trim {
    my $line = shift;

    # Strip whitespace at the beginning and end
    $line =~ s/^\s*(.*?)\s*$/\1/;

    # If the line starts with #, we're done
    return ""
        if ($line =~ /^#/);

    # Strip comments.  Leave escaped hashes ("\#").
    $line =~ s/^(.*?)(?<=[^\\])#.*$/\1/;

    # Convert escape hashes to regular hashes
    $line =~ s/\\#/#/g;

    return $line;
}

#
# Function to load the config file
#
sub load_config {
    my $file = shift;

    # If no config file was specified, just return
    return
        if (!defined($file));

    # Abort if we can't read the specified file
    die "Cannot read config file $file"
        if (! -r $file);

    open(IN, $file) || die "Cannot read config file $file";
    my $line_num = 0;
    while (<IN>) {
        chomp;
        ++$line_num;

        # Strip leading and trailing whitespace and comments
        my $line = _trim($_);
        next
            if (length($line) == 0);

        # Split into "name = value".  Check for a few bozo errors.
        my $result = ($line =~ /^\s*(\S+)\s*=\s*(.*?)\s*$/);
        if (!$result) {
            Warning("Syntax error line $line_num in $file (ignored): $line\n");
        } else {
            my $key = lc($1);
            my $value = $2;

            if (defined($config->{$key})) {
                Warning("Duplicate key line $line_num in $file (ignored): $line\n");
            } else {
                $config->{$key} = $value;
            }
        }
    }

    Debug("===Config===");
    DebugDump($config);
}

#
# Function to return a config value, or the default value if that key
# was not defined.
#
sub get {
    my $key = shift;
    my $default = shift;

    return $config->{$key}
        if (defined($config->{$key}));
    return $default;
}

#
# Function to parse a whitespace-delimited list of values from the
# config.  Returns an array if the key was defined in the config, or
# the default array.
#
sub parse_config_list {
    my $key = shift;
    my @default = @_;

    if (defined($config->{$key})) {
        return split(/\s+/, $config->{$key});
    }

    # If we didn't find a value, return the default value
    return @default;
}

#
# Function to parse a time value from the config.  Returns an integer
# number of seconds, or the default value if the key was not specified
# in the config.
#
sub parse_config_time {
    my $key = shift;
    my $default = shift;

    if (defined($config->{$key})) {
        my ($hours, $mins, $secs);

        $hours = $mins = $secs = 0;
        if ($config->{$key} =~ m/^(\d+):(\d{1,2}):(\d{1,2})$/) {
            $hours = $1;
            $mins = $2;
            $secs = $3;
        } elsif ($config->{$key} =~ m/^(\d+):(\d{1,2})$/) {
            $mins = $1;
            $secs = $2;
        } elsif ($config->{$key} =~ m/^(\d+)$/) {
            $secs = $1;
        } else {
            print "Invalid time specified for $key config parameter: $config->{$key} (ignored)\n";
            return undef;
        }

        return 
            ($hours * 60 * 60) +
            ($mins * 60) +
            $secs;
    }

    # If we didn't find a value, return the default value
    return $default;
}


#
# Function to take a number of seconds and return a prettyprint string
# in the form of [h:]m:ss.  Notes:
#
# - h may be >99
# - if h > 0, output will be h:mm:ss, with mm and ss zero-padded to 2 digits
# - if h == 0, output will be m:ss, with ss zero-padded to 2 digits
#
sub make_time_str {
    my $secs = shift;
    my $orig = $secs;

    my $hours = floor($secs / 3600);
    $secs -= $hours * 3600;
    my $mins = floor($secs / 60);
    $secs -= $mins * 60;

    if ($hours > 0) {
        return sprintf("%d:%02d:%02d", $hours, $mins, $secs);
    } else {
        return sprintf("%d:%02d", $mins, $secs);
    }
}

1;
